#!/usr/bin/python3

import yaml
import json
import sys
import os
import subprocess
import getopt

def printUsage():
    print('Generate configtx.yaml\nUsage:')
    print('    gen_configtxg_from_template.py -o <orderer_num> -p <peer_num>')
    print('    or: gen_configtxg_from_template.py --orderer_num=<orderer_num> --peer_num=<peer_num>')
 
def parseArgs(argv):
    global orderer_num
    global peer_num
    opts, args = getopt.getopt(argv[1:], "ho:p:t:u:", ["help", "orderer_num=", "peer_num="])

    if len(opts) > 2 or len(args) != 0:
        print('Invalid paramater')
        sys.exit()
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            printUsage()
            sys.exit()
        elif opt in ("-o", "--orderer_num"):
            orderer_num = int(arg)
        elif opt in ("-p", "--peer_num"):
            peer_num = int(arg)

def gen_compose_orderer():
    for i in range(1, orderer_num + 1):
        orderer = {
            "version": "2",
            "volumes": {
                f'orderer{i}.demo.com': None
            },
            "networks": {
                f"{network}": {"name": f"{network}"}
            },
            "services": {
                f"orderer{i}.demo.com": {
                "container_name": f"orderer{i}.demo.com",
                "extends": {
                    "file": "docker-compose-base.yaml",
                    "service": "orderer-base"
                },
                "volumes": [
                    "../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block",
                    f"../crypto-config/ordererOrganizations/demo.com/orderers/orderer{i}.demo.com/msp:/var/hyperledger/orderer/msp",
                    f"../crypto-config/ordererOrganizations/demo.com/orderers/orderer{i}.demo.com/tls/:/var/hyperledger/orderer/tls",
                    # f"orderer{i}.demo.com:/var/hyperledger/production/orderer"
                ],
                "ports": [
                    f"{orderer_port_start + i - 1}:{orderer_port_start + i - 1}"
                ],
                "networks": [
                    f"{network}"
                ]
                }
            }
        }
        with open(f'{current_folder}/docker-compose-order' + str(i) + '.yaml', 'w', encoding='utf8') as f:
            yaml.dump(orderer, f, default_flow_style=False, allow_unicode=True, sort_keys=False)

def gen_compose_peer():
    for i in range(1, peer_num + 1):
        peer = {
            "version": "2",
            "volumes": {
                f"peer0.org{i}.demo.com": None
            },
            "networks": {
                f"{network}": {"name": f"{network}"}
            },
            "services": {
                f"peer0.org{i}.demo.com": {
                    "container_name": f"peer0.org{i}.demo.com",
                    "extends": {
                        "file": "docker-compose-base.yaml",
                        "service": "peer-base"
                    },
                    "environment": [
                        f"CORE_PEER_ID=peer0.org{i}.demo.com",
                        f"CORE_PEER_ADDRESS=peer0.org{i}.demo.com:{peer_port_start + i}",
                        f"CORE_PEER_LISTENADDRESS=0.0.0.0:{peer_port_start + i}",
                        f"CORE_PEER_CHAINCODEADDRESS=peer0.org{i}.demo.com:{peer_port_start + i + 100}",
                        f"CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:{peer_port_start + i + 100}",
                        f"CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org{i}.demo.com:{peer_port_start + i}",
                        f"CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org{i}.demo.com:{peer_port_start + i}",
                        f"CORE_PEER_LOCALMSPID=Org{i}MSP"
                    ],
                    "volumes": [
                        "/var/run/docker.sock:/host/var/run/docker.sock",
                        f"../crypto-config/peerOrganizations/org{i}.demo.com/peers/peer0.org{i}.demo.com/msp:/etc/hyperledger/fabric/msp",
                        f"../crypto-config/peerOrganizations/org{i}.demo.com/peers/peer0.org{i}.demo.com/tls:/etc/hyperledger/fabric/tls"
                    ],
                    "ports": [
                        f"{peer_port_start + i}:{peer_port_start + i}"
                    ],
                    "networks": [
                        f"{network}"
                    ],
                    "extra_hosts": []
                },
                "cli": {
                    "container_name": "cli",
                    "image": "hyperledger/fabric-tools:$IMAGE_TAG",
                    "tty": True,
                    "stdin_open": True,
                    "environment": [
                        "GOPATH=/opt/gopath",
                        "CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock",
                        "FABRIC_LOGGING_SPEC=INFO",
                        "CORE_PEER_ID=cli",
                        f"CORE_PEER_ADDRESS=peer0.org{i}.demo.com:{peer_port_start + i}",
                        f"CORE_PEER_LOCALMSPID=Org{i}MSP",
                        "CORE_PEER_TLS_ENABLED=True",
                        f"CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org{i}.demo.com/peers/peer0.org{i}.demo.com/tls/server.crt",
                        f"CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org{i}.demo.com/peers/peer0.org{i}.demo.com/tls/server.key",
                        f"CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org{i}.demo.com/peers/peer0.org{i}.demo.com/tls/ca.crt",
                        f"CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org{i}.demo.com/users/Admin@org{i}.demo.com/msp"
                    ],
                    "working_dir": "/opt/gopath/src/github.com/hyperledger/fabric/peer",
                    "command": "/bin/bash",
                    "volumes": [
                        "/var/run/:/host/var/run/",
                        "./../chaincode/:/opt/gopath/src/github.com/chaincode",
                        "../crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/",
                        # "./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/",
                        "../channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts"
                    ],
                    "depends_on": [
                        f"peer0.org{i}.demo.com"
                    ],
                    "networks": [
                        f"{network}"
                    ],
                    "extra_hosts": []
                }
            }
        }
        extra_hosts = []
        # print(FABRIC_ORDERER_IPs)
        # print(FABRIC_PEER_IPs)
        for j in range(1, orderer_num + 1):
            extra_hosts.append(f"orderer{j}.demo.com:{FABRIC_ORDERER_IPs[j - 1]}")
        for j in range(1, peer_num + 1):
            extra_hosts.append(f"peer0.org{j}.demo.com:{FABRIC_PEER_IPs[j - 1]}")
        peer["services"][f"peer0.org{i}.demo.com"]["extra_hosts"] = extra_hosts
        peer["services"]["cli"]["extra_hosts"] = extra_hosts
        with open(f'{current_folder}/docker-compose-org' + str(i) + '.yaml', 'w', encoding='utf8') as f:
            yaml.dump(peer, f, default_flow_style=False, allow_unicode=True, sort_keys=False)

def get_array_from_conf_file(file_path, variable_name):
    # 创建一个新的Shell进程并在其中运行配置文件
    process = subprocess.Popen(
        ['bash', '-c', f'source {file_path}' + "&& echo -n ${" + f'{variable_name}' + "[@]}"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    
    # 读取进程的输出并解析为环境变量
    output, error = process.communicate()
    env_vars = output.decode('utf-8').split(' ')

    return env_vars

# 运行配置文件并获取环境变量
current_folder = os.path.dirname(os.path.abspath(__file__))
FABRIC_PEER_IPs = get_array_from_conf_file(f'{current_folder}/../../../cluster_IP.conf', 'FABRIC_PEER_IPs')
FABRIC_ORDERER_IPs = get_array_from_conf_file(f'{current_folder}/../../../cluster_IP.conf', 'FABRIC_ORDERER_IPs')

orderer_num = 1
peer_num = 4
network = "fabric-demo-network"
orderer_port_start = 7050
peer_port_start = 7100

if __name__ == "__main__":
    parseArgs(sys.argv)

    # with open("docker-compose-org1-peer0.yaml", "r", encoding="utf-8") as file:
    #     yaml_data = yaml.full_load(file)

    # # 将加载的YAML数据转换为JSON格式
    # json_data = json.dumps(yaml_data, indent=2)
    # print(json_data)

    gen_compose_orderer()
    gen_compose_peer()

    # print(FABRIC_ORDERER_IPs)
    # print(FABRIC_PEER_IPs)

    # with open('docker-compose-order1-gen.yaml', 'w', encoding='utf8') as f:
    #     yaml.dump(configtx, f, default_flow_style=False, allow_unicode=True, sort_keys=False)